#include "LibBase.h"
#include "C_Socket.h"
#pragma comment(lib, "ws2_32.lib")

C_Socket::C_Socket()
{
	m_iDomain = -1;
    m_iType = -1;
	m_hSocket = 0;
}

C_Socket::~C_Socket()
{

}

int C_Socket::Open(int iDomain, int iType, int iProtocol)
{
  m_iDomain = iDomain;
  m_iType = iType;

  m_hSocket = socket(m_iDomain, iType, iProtocol);

  if(m_hSocket == 0)
  {
    Log("Error","C_Socket::Open","socket can not open");
	return -1;
  }

  return 1;
}

int C_Socket::Close()
{

  int iRc = closesocket(m_hSocket);

  if(iRc)
  {
	   Log("Error","C_Socket::Close","socket can not close");
	   return -1;
  }

  return 1;
    
}

int C_Socket::GetDomain()
{
	
	return m_iDomain;
}

void C_Socket::SetOption(int iLevel, int iOpt, const char* pOptVal, socklen_t iOptLen)
{
  int iRc = setsockopt(m_hSocket, iLevel, iOpt, pOptVal,
                       iOptLen);

  if(iRc)
  {
     Log("Error","C_Socket::SetOption","setoption is failded");
  }
}

void C_Socket::GetOption(int iLevel, int iOpt, char* pOptVal, socklen_t* pOptLen)
{
  int iRc = getsockopt(m_hSocket, iLevel, iOpt, pOptVal,
                       pOptLen);

  if(iRc)
  {
     Log("Error","C_Socket::GetOption","GetOption is failded");
  }
}


//------------------------------------------------------------------------------
//
//------------------------------------------------------------------------------
int C_Socket::Bind(char* pcaddr, char*pcport)
{
	// Try to resolve the given address
	


	if(m_hSocket<0)
	{
	 Log("Error","C_Socket::Bind","Socket is wrong");
	 return -1;
	}

  struct sockaddr_in Addr;
  if (pcaddr == NULL || strcmp(pcaddr,"127.0.0.1") == 0)
  {
	Addr.sin_addr.s_addr = htonl(INADDR_ANY);
  }
  else
  {
	  Addr.sin_addr.s_addr = inet_addr(pcaddr);
  }
  Addr.sin_family = AF_INET;
  Addr.sin_port = htons(atoi(pcport));

  // Bind the socket to the local address
  int iRc = bind(m_hSocket, (sockaddr*)&Addr, sizeof(Addr));
  if(iRc)
  {
   Log("Error","C_Socket::Bind","Bind is failed");
   return -1;
  }
   Log("Info","C_Socket::Bind","Bind is OK");
  return 1;
}
  

//------------------------------------------------------------------------------
//
//------------------------------------------------------------------------------
int C_Socket::Connect(char* strPeer, char* strPort)
{
  // Try to resolve the given address
  struct sockaddr_in Addr;
 

  Addr.sin_addr.s_addr = inet_addr(strPeer);
  Addr.sin_port = htons(atoi(strPort));
  Addr.sin_family = AF_INET;

  // Bind the socket to the local address
  int iRc = connect(m_hSocket, (sockaddr*)&Addr, sizeof(struct sockaddr));
  if(iRc)
  {
     Log("Error","C_Socket::Connect","Connect is failded");
	 return -1;
  }

	 Log("Info"," C_Socket::Connect","Connect is Ok");
	return 1;
}

//------------------------------------------------------------------------------
//
//------------------------------------------------------------------------------
int C_Socket::Listen(int iBacklog)
{
  int iRc = listen(m_hSocket, iBacklog);
  if(iRc)
  {
    Log("Error","C_Socket::Listen","Listen is failded");
	return -1;
  }

   Log("Info","C_Socket::Listen","Listen is OK");
	return 1;
}


//------------------------------------------------------------------------------
//
//------------------------------------------------------------------------------
unsigned int C_Socket::Accept(char* pcClientIP,char* pcClientPort)
{
	SOCKET sRc = 0;  
    struct sockaddr_in sPeer;
    socklen_t iAddrLen = sizeof(sPeer);
  
    sRc = accept(m_hSocket, (struct sockaddr*)&sPeer, &iAddrLen);


 

  if(sRc == 0)
  {
    Log("Error","C_Socket::Accept","Accept is failded");
	return -1;
  }
  else
  {
    strcpy(pcClientIP,inet_ntoa(sPeer.sin_addr));

	itoa(ntohs(sPeer.sin_port),pcClientPort,10);

  

  }
  Log("Info","C_Socket::Accept","Accept is OK");
  return sRc;
}


int C_Socket::Recv(SOCKET m_RecSocket,char* pBuff,int iBuffLen,int iFlags)
{
  int iRc;
	if (pBuff == NULL || iBuffLen == 0 )
	{
	Log("Error","C_Socket::recv","Input is NULL");
	return -1;
	}

  // Wait for data until something is received

  if (m_RecSocket == NULL)
  {
	 iRc =  recv(m_hSocket, pBuff, iBuffLen, iFlags);
  }
  else
  {
	iRc = recv(m_RecSocket, pBuff, iBuffLen, iFlags);
  }


  if(iRc < 0)
	{
    Log("Error","C_Socket::recv","recv is failed");
	return -1;
	}

	return iRc;
}

int C_Socket::Recvfrom(char* pcPeerAddr,char* pcPeerPort,char* pBuff, int iBuffLen, int iFlags)
{
	if (pBuff == NULL || iBuffLen == 0)
	{
		  Log("Error","C_Socket::recv","Input is NULL");
		  return -1;
	}

  // Wait for data until something is received
 
	struct sockaddr_in from;	
	int ifromlen = sizeof(from);
	int iRc = recvfrom(m_hSocket, pBuff, iBuffLen, iFlags,(sockaddr*)&from,&ifromlen);

	strcpy(pcPeerAddr,inet_ntoa(from.sin_addr));
	itoa(ntohs(from.sin_port),pcPeerPort,10);

	

    return iRc;
}


int C_Socket::Send(SOCKET m_SendSocket,char* pBuff, int iBuffLen, int iFlags)
{
	
	int iRc = 0;
	if (pBuff == NULL || iBuffLen == 0)
	{
		  Log("Error","C_Socket::send","Input is NULL");
		  return -1;
	}


  // Wait until the data could be sent

	if (m_SendSocket == NULL)
	{
	iRc = send(m_hSocket, pBuff, iBuffLen, iFlags);
	}
	else
	{
	  iRc = send(m_SendSocket, pBuff, iBuffLen, iFlags);
	}


	if(iRc < 0)
	{
	Log("Error","C_Socket::send","send is failed");
	return -1;
	}

	return iRc;
}

int C_Socket::Sendto(char* pcPeerAddr,char* pcPeerPort,char* pBuff, int iBuffLen, int iFlags)
{
 
	if (pBuff == NULL || iBuffLen == 0 || pcPeerAddr == NULL || pcPeerPort == NULL)
	{
		  Log("Error","C_Socket::sendto","Input is NULL");
		  return -1;
	}

	struct sockaddr_in to;
	to.sin_family = AF_INET;
	to.sin_port = htons(atoi(pcPeerPort));
	to.sin_addr.s_addr = inet_addr(pcPeerAddr);
	
    int iRc = sendto(m_hSocket, pBuff, iBuffLen, iFlags,
                   (sockaddr*)&to,
                   sizeof(to));

 

   return iRc;
}


/************************************************************************/
/*                                                                      */
/************************************************************************/

//------------------------------------------------------------------------------
//
//------------------------------------------------------------------------------
char* C_Socket::GetLocalName()
{
	char* strLocalName = new char[100];
	struct sockaddr_in saIntf;
	socklen_t iNameLen = sizeof(saIntf);
	int iRc = getsockname(m_hSocket, (struct sockaddr*)&saIntf, &iNameLen);

	if(iRc)
	{
	  Log("Error","C_Socket::GetLocalName","GetLocalName is failed");
	  delete []strLocalName;
	}
	else
	{
		strcpy(strLocalName,inet_ntoa(saIntf.sin_addr));
	}
      
  
  return strLocalName;
}


//------------------------------------------------------------------------------
//
//------------------------------------------------------------------------------
char* C_Socket::GetLocalPort() 
{
	char* strLocalPort = new char[100];

    struct sockaddr_in saIntf;
    socklen_t iNameLen = sizeof(saIntf);
    int iRc = getsockname(m_hSocket, (struct sockaddr*)&saIntf, &iNameLen);
  
    if(iRc)
    {
       Log("Error","C_Socket::GetLocalPort() ","GetLocalPort is failed");
	   delete []strLocalPort;
	   return NULL;
    }
    else
	{
		itoa(saIntf.sin_port,strLocalPort,10);
	}
     
    return strLocalPort;
}


//------------------------------------------------------------------------------
//
//------------------------------------------------------------------------------
char* C_Socket::GetPeerName() 
{
  
	char* strPeerName = new char[100];

    struct sockaddr_in saPeer;
    socklen_t iNameLen = sizeof(saPeer);
    int iRc = getpeername(m_hSocket, (struct sockaddr*)&saPeer, &iNameLen);
    
    if(iRc)
    {
      Log("Error","C_Socket::GetPeerName","GetPeerName is failed");
	  delete []strPeerName;
	  return NULL;
    }
    else
	{
	  strcpy(strPeerName,inet_ntoa(saPeer.sin_addr));
	}
     
   return strPeerName;
}


//------------------------------------------------------------------------------
//
//------------------------------------------------------------------------------
char* C_Socket::GetPeerPort() 
{
 	char* strPeerPort = new char[100];

    struct sockaddr_in saPeer;
    socklen_t iNameLen = sizeof(saPeer);
    int iRc = getpeername(m_hSocket, (struct sockaddr*)&saPeer, &iNameLen);
       if(iRc)
    {
     	Log("Error","C_Socket::GetPeerPort","GetPeerPort is failed");
		delete []strPeerPort;
		return NULL;
	}
	else
	{
		sprintf(strPeerPort,"%d",saPeer.sin_port) ;    
	}


  return strPeerPort;
}




